package org.subside.model.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @Author : zhangbo
 * @data : 2024/5/15
 * @description :切面配置类 基于注解实现
 */
@Aspect
//组件配置
@Component
//优先级，数值越小优先级越高
@Order(1)
@Slf4j
public class controllerAop {
    /** AOP核心概念
     *  Joinpoint (连接点):指那些被拦截到的点，在spring中，可以动态代理拦截的目标类方法。
     *  Pointcut(切入点):指要对哪些jointpoint进行拦截处理，即被拦截的连接点。
     *  Advice(通知)：指被拦截到joinpoint之后要做的事情，即对切入点内容的增强。
     *  Target(目标)：指代理的目标对象。
     *  Weaving(植入):指把增强的代码应用到目标对象上，生成代理对象的过程。
     *  Proxy(代理):指生成的代理对象。
     *  Aspect(切面):切入点和通知的结合。
     */
    /** 通知
     * before：前置通知，通知方法在目标方法调用前执行
     * after：后置通知，通知方法在目标方法执行后调用
     * after-returning 返回后通知，通知方法会在目标方法返回后调用
     * after-throwing 抛出异常通知，通知方法会在目标方法泡池异常后调用
     * around 环绕通知，通知方法会将目标方法封装起来
     */

    /**
     *@Pointcut
     * @within 使用@within注解类型，匹配所有持有指定注解类型的方法，注解类型也必须是全限定类型名称。
     * 此处注解类型为Controller，事务都生效
     */
    @Pointcut("@within(org.springframework.stereotype.Controller)")
    private void method(){
        //定义一个切入点
    }

    @Around("method()")
    public Object doSomething(ProceedingJoinPoint joinPoint){
        try {
            //执行方法
            Object proceed = joinPoint.proceed();
            log.info("环绕通知");
            return proceed;
        } catch (Throwable e) {
            log.info("异常："+e);
            throw new RuntimeException(e);
        }
        /**
         * AccountServiceImp.update()对不同的业务方法进行处理
         *
         */
//        @Pointcut("execution(* com.apesource.service.AccountServiceImp.update())")
//        public void dian(){
//
//        }
//
//        //前置通知
//        @Before("dian()")
//        public void beforeMethod(){
//            System.out.println("前置通知==>日志类logger中调用BeforeLogger方法进行日志记录");
//        }
//
//        //返回通知
//        @AfterReturning("dian()")
//        public void returnMethod(){
//            System.out.println("返回通知");
//        }
//        //异常通知
//        @AfterThrowing("dian()")
//        public void throwingMethod(){
//            System.out.println("异常通知");
//        }
//
//        //后置通知
//        @After("dian()")
//        public void afterMethod(){
//            System.out.println("后置通知");
//        }
//
//
////    @Around("dian()")
//        public Object arroundMethod(ProceedingJoinPoint pjp){
//
//            Object obj =null;
//
//            try {
//                System.out.println("前置通知环绕通知的");
//                //主业务代码
//                Object[] args =pjp.getArgs();
//                obj =pjp.proceed(args);
//                int a = 10/0;
//                System.out.println("返回通知");
//            } catch (Throwable throwable) {
//                throwable.printStackTrace();
//                System.out.println("异常通知");
//            } finally {
//                System.out.println("后置通知");
//            }
//            return obj;

        }
}
